package cn.z2huo.demo.hello.core.message.impl;

import cn.z2huo.demo.hello.MessageProperties;
import cn.z2huo.demo.hello.core.common.TransactionCodeHolder;
import cn.z2huo.demo.hello.core.exception.BusinessException;
import cn.z2huo.demo.hello.core.message.api.ResponseMessageFactory;
import cn.z2huo.demo.hello.core.message.model.ResponseMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;

/**
 * <p>
 *
 * @author z2huo
 */
@Slf4j
@RequiredArgsConstructor
public class ResponseMessageFactoryImpl implements ResponseMessageFactory {

    public static final String SUCCESS_CODE = "0000";

    public static final String FAILD_CODE = "9999";

    private final MessageProperties messageProperties;

    @Override
    public ResponseMessage getSuccessMessage() {
        return null;
    }

    @Override
    public ResponseMessage getSuccessMessage(Object data) {
        return null;
    }

    @Override
    public ResponseMessage getSuccessMessage(String content) {
        return null;
    }

    @Override
    public ResponseMessage getFaildMessage(Throwable exceptionInfo) {
        return null;
    }

    @Override
    public ResponseMessage getFaildMessage(Throwable exceptionInfo, String content) {
        return null;
    }

    private String findMessageContent(Throwable exceptionInfo, StringBuilder initMessageBuffer) {
        // 如果传入的initMessageBuffer为空，则代表是第一次执行。需要初始化StringBuilder
        if (initMessageBuffer == null)
            initMessageBuffer = new StringBuilder();
        else
            initMessageBuffer.append(RESPONSE_MESSAGE_SPLIT_FLAG);
        /**
         * 先尝试查找框架预制的中文消息，如果找到，则放入预制信息
         */
        String exceptionMessage = findMessageContent(findMessageCode(exceptionInfo));
        /**
         * 如果预制消息内容不存在，则用{@code exceptionMessage}内容
         */
        if (StringUtils.isEmpty(exceptionMessage))
            exceptionMessage = StringUtils.defaultString(exceptionInfo.getMessage(), findMessageContent(FAILD_CODE));
        /**
         * 如果已经在既有的消息中找到了当前异常的描述，则代表有效堆栈已经到了底端，可以退出了
         */
        if (StringUtils.isNotEmpty(initMessageBuffer) && initMessageBuffer.indexOf(exceptionMessage) != -1)
            return initMessageBuffer.toString();
        initMessageBuffer.append(exceptionMessage);
        // 如果Cause不为空，递归生成消息内容
        if (exceptionInfo.getCause() != null)
            return findMessageContent(exceptionInfo.getCause(), initMessageBuffer);
        return initMessageBuffer.toString();
    }

    private String findMessageCode(Throwable exceptionInfo) {
        /**
         * 解析出消息编码
         */
        String generalMessageCode = findMessageCode(exceptionInfo.getClass().getName());
        /**
         * 如果异常类型为{@link BusinessException}, 则需要将 MessgeCode 与 ErrorCode 进行拼接
         */
        if (exceptionInfo instanceof BusinessException) {
            BusinessException be = (BusinessException) exceptionInfo;
            return generalMessageCode + ":" + be.getErrorCode();
        }
        /**
         * 如果消息码依然是空的，则判断抛出的异常是否为每个声明异常的子类。
         */
        if (StringUtils.isEmpty(generalMessageCode)) {
            Iterator<String> expTypeIter = messageProperties.getException().getTypes().values().iterator();
            // 迭代声明集合的每一个元素
            while (expTypeIter.hasNext()) {
                String typeStr = expTypeIter.next();
                if (typeStr.equals(messageProperties.getException().getTypes().get(SUCCESS_CODE))
                        || typeStr.equals(messageProperties.getException().getTypes().get(FAILD_CODE)))
                    continue;
                try {
                    if (Class.forName(typeStr).isAssignableFrom(exceptionInfo.getClass())) {
                        return findMessageCode(typeStr);
                    }
                } catch (ClassNotFoundException e) {
                    if (log.isDebugEnabled())
                        log.debug(e.getMessage(), e);
                }
            }
        } else {
            return generalMessageCode;
        }
        /**
         * 如果消息码依然是空的，则直接取默认值9999
         */
        return FAILD_CODE;
    }

    /**
     * 直接从 {@link #messageProperties} 中查找消息编码对应的异常信息
     */
    private String findMessageCode(String exceptionType) {
        return messageProperties.getException().getTypes().keySet().stream()
                .filter(key -> messageProperties.getException().getTypes().get(key).equals(exceptionType))
                .findFirst()
                .orElse(FAILD_CODE);
    }

    /**
     * 直接从 {@link #messageProperties} 中查找消息编码对应的异常描述
     *
     * @param messageCode 消息编码
     * @return 异常描述
     * @author maeagle
     * @since 3.1.0
     */
    private String findMessageContent(String messageCode) {
        return messageProperties.getException().getMessages().getOrDefault(messageCode, "");
    }

    private ResponseMessage createResponseMessage() {
        ResponseMessage responseMessage = new ResponseMessage();
        responseMessage.setDateTime(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
                .setTransactionCode(TransactionCodeHolder.get());
        return responseMessage;
    }
}
